#pragma once
#include "Core.h"
#include "Engine.h"
#include "Tickable.h"
#include <string>
#include <memory>
//#include "alibabacloud/oss/utils/Outcome.h"
//#include "GenericPlatform/GenericPlatformHttp.h"
#include "OssTaskTickMag.h"
#include "OSSInfo.h"
//#include "AliyunOssTask.generated.h"

namespace AlibabaCloud
{
	namespace OSS 
	{
		class ServiceRequest;	
		class OssClient;
		class GetObjectRequest;
		class AsyncCallerContext;
		class OssError;
		class GetObjectResult;
		template<typename  E, typename  R>
		class Outcome;
	

	}
}


class ALIYUNCPPPLUGIN_API FAliyunOssTask : public FNonAbandonableTask,public IOssTaskTick
{

public:

	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(FAliyunOssTask, STATGROUP_ThreadPoolAsyncTasks);
	}

	FAliyunOssTask(const FAliyunOssTaskInfo& taskInfo);

	//callback Must be in the game thread
	FAliyunOssTask(const FAliyunOssTaskInfo& taskInfo, const FOssCallBackFunction& callback, void* InUserData = nullptr);

	virtual ~FAliyunOssTask();

	FAliyunOssTask(FAliyunOssTask&) = delete;
	FAliyunOssTask& operator=(const FAliyunOssTask&) = delete;

	//<0 大小获取失败;  =0 oss没有返回数据  ； >0正常获取到大小  单位Bit
	int64 GetDataSize();

	FString GetTaskID()const;

	void DoWork();

	bool CanAbandon();

	bool IsSuccess()const;

	FString GetMsg()const;

	FString GetErrorMsg()const;
	FString GetErrorCode()const;

	FOssTimeTakeNotes GetTakeNotes()const;

	void TickTask(const float& DeltaTime)override;

	static bool DoSynchronizationTask(const FAliyunOssTaskInfo& taskInfo,FString* outMsg = nullptr);

private:
	void HandleDownloadByObject();
	void HandleUploadByObject();
	void HandleDownloadByURL();
	void HandleUploadByURL();
	void HandleBufferDataUploadByObject();



	void ProgressCallback(size_t increment, int64_t transfered, int64_t total, void* userData);

	void GetObjectAsyncCallFunction(
		const AlibabaCloud::OSS::OssClient* client
		,const AlibabaCloud::OSS::GetObjectRequest& ObjectRequest
		//, const AlibabaCloud::OSS::GetObjectOutcome& Outcome
		, const class AlibabaCloud::OSS::Outcome<AlibabaCloud::OSS::OssError, AlibabaCloud::OSS::GetObjectResult>& Outcome
		, const std::shared_ptr<const AlibabaCloud::OSS::AsyncCallerContext>& asyncCallerPtr
	);

	void OnProgressCallBack()const;

	void BindServiceRequest(AlibabaCloud::OSS::ServiceRequest& request);

	void TaskComplete(bool isSuccess,const FString& errorCode, const FString& errorMessage);

public:
	const FAliyunOssTaskInfo m_TaskInfo;

private:
	FString taskGuid;
	bool inGameThread;
	FString backMsg;
	FString errorCodeBuffer;
	FString errorMeeageBuffer;
	bool waitFor;
	bool taskIsSuccess;
	TAtomic<float> m_Percent;
	FOssCallBackFunction m_callbackEv;
	void* m_pUserData;
	FOssTimeTakeNotes takeNotes;

};

class ALIYUNCPPPLUGIN_API FAliyunOssTaskDeleteObjects : public FNonAbandonableTask
{
#define OssObjectsOperNumLimit 1000
	/*为什么用private?
	因为删除文件是个不可逆的过程, 太他妈危险了, 暂时不公开给其他人使用
	*/

private:
	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(FAliyunOssTaskDeleteObjects, STATGROUP_ThreadPoolAsyncTasks);
	}

	FAliyunOssTaskDeleteObjects(const FString& InBucketname, const FString& InPrefix);
	FAliyunOssTaskDeleteObjects(const FString& InBucketname, const TArray<FString>& InOssObjectFiles);
	virtual ~FAliyunOssTaskDeleteObjects() {}
	virtual void DoWork();

private:
	const std::string m_strBucketName;
	TArray<std::string> m_arrDeleteFiles;
};


//
//class ALIYUNCPPPLUGIN_API FAliyunOssGraphTask
//{
//public:
// 
//	static const TCHAR* GetTaskName()
//	{
//		return TEXT("FAliyunOssGraphTask");
//	}
//	FORCEINLINE static TStatId GetStatId()
//	{
//		RETURN_QUICK_DECLARE_CYCLE_STAT(FAliyunOssGraphTask, STATGROUP_TaskGraphTasks);
//	}	
//	static ENamedThreads::Type GetDesiredThread()
//	{
//		return ENamedThreads::AnyBackgroundThreadNormalTask;
//	}
//	static ESubsequentsMode::Type GetSubsequentsMode()
//	{
//		return ESubsequentsMode::TrackSubsequents;
//	}
//
//	FAliyunOssGraphTask(const FAliyunOssTaskInfo& taskInfo,void* InUserData = nullptr, bool InCheckByETag = false)
//		: m_TaskInfo(taskInfo)
//		, m_pUserData(InUserData)	
//        , m_bCheckByETag(InCheckByETag)
//		, m_bUpdateIsSuccess(false)  
//     
//	{
//
//	}
//
//	FAliyunOssGraphTask(const FAliyunOssTaskInfo& taskInfo,const FAliOssOnCompleteWithMsg& onCompleteWithMsg
//		, void* InUserData = nullptr, bool InCheckByETag = false)
//		: m_TaskInfo(taskInfo)
//		, m_pUserData(InUserData)
//        , m_bCheckByETag(InCheckByETag)
//        , m_bUpdateIsSuccess(false) 
//		, m_OnCompleteWithMsg(onCompleteWithMsg)
//	{
//
//	}
//
//
//
//	FAliyunOssGraphTask(const FAliyunOssTaskInfo& taskInfo, const FString& InContentData)
//		: m_TaskInfo(taskInfo.bucketName,taskInfo.objectKey,taskInfo.inOssObjectFilePath,InContentData)
//		, m_pUserData(nullptr)
//        , m_bCheckByETag(false)
//        , m_bUpdateIsSuccess(false)       
//	{
//
//	}
//
//	virtual ~FAliyunOssGraphTask();
//
//	void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& CompletionGraphEvent);
//
//	//void TickTask(const float& DeltaTime)override;
//
//private:
//	void HandleDownloadByObject();
//	void HandleUploadByObject();
//	void HandleDownloadByURL();
//	void HandleUploadByURL();
//	void HandlePanoImageUploadByObject();
//	void HandleBufferDataUploadByObject();
//
//	void CallOnCompleteWithMsg();
//
//
//private:
//	
//	const FAliyunOssTaskInfo m_TaskInfo;
//	void* m_pUserData;
//	bool m_bCheckByETag;
//	bool m_bUpdateIsSuccess;
//
//	FAliOssOnCompleteWithMsg m_OnCompleteWithMsg;
//
//};
